Package org.pushingpixels.flamingo.internal.ui.ribbon

Source Code of org.pushingpixels.flamingo.internal.ui.ribbon.BasicRibbonBandUI$CollapsedButtonPopupPanel

/*
* Copyright (c) 2005-2010 Flamingo Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*  o Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*    
*  o Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*    
*  o Neither the name of Flamingo Kirill Grouchnikov nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*    
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.pushingpixels.flamingo.internal.ui.ribbon;

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.*;

import org.pushingpixels.flamingo.api.common.*;
import org.pushingpixels.flamingo.api.common.icon.ResizableIcon;
import org.pushingpixels.flamingo.api.common.popup.*;
import org.pushingpixels.flamingo.api.ribbon.*;
import org.pushingpixels.flamingo.api.ribbon.resize.IconRibbonBandResizePolicy;
import org.pushingpixels.flamingo.api.ribbon.resize.RibbonBandResizePolicy;
import org.pushingpixels.flamingo.internal.ui.common.BasicCommandButtonUI;
import org.pushingpixels.flamingo.internal.utils.FlamingoUtilities;
import org.pushingpixels.flamingo.internal.utils.RenderingUtils;
import org.pushingpixels.trident.Timeline;
import org.pushingpixels.trident.swing.SwingRepaintCallback;

/**
* Basic UI for ribbon band {@link JRibbonBand}.
*
* @author Kirill Grouchnikov
* @author Matt Nathan
*/
public class BasicRibbonBandUI extends RibbonBandUI {
  /**
   * The associated ribbon band.
   */
  protected AbstractRibbonBand ribbonBand;

  /**
   * The button for collapsed state.
   */
  protected JCommandButton collapsedButton;

  /**
   * The band expand button. Is visible when the
   * {@link JRibbonBand#getExpandActionListener()} of the associated ribbon
   * band is not <code>null</code>.
   */
  protected AbstractCommandButton expandButton;

  protected float rolloverAmount;

  protected Timeline rolloverTimeline;

  /**
   * Mouse listener on the associated ribbon band.
   */
  protected MouseListener mouseListener;

  /**
   * Listens to property changes on the associated ribbon band.
   */
  protected PropertyChangeListener propertyChangeListener;

  /**
   * Action listener on the expand button.
   */
  protected ActionListener expandButtonActionListener;

  /**
   * Popup panel that shows the contents of the ribbon band when it is in a
   * collapsed state.
   *
   * @author Kirill Grouchnikov
   */
  protected static class CollapsedButtonPopupPanel extends JPopupPanel {
    /**
     * The main component of <code>this</code> popup panel. Can be
     * <code>null</code>.
     */
    protected Component component;

    /**
     * Creates popup gallery with the specified component.
     *
     * @param component
     *            The main component of the popup gallery.
     * @param originalSize
     *            The original dimension of the main component.
     */
    public CollapsedButtonPopupPanel(Component component,
        Dimension originalSize) {
      this.component = component;
      this.setLayout(new BorderLayout());
      this.add(component, BorderLayout.CENTER);
      // System.out.println("Popup dim is " + originalSize);
      this.setPreferredSize(originalSize);
      this.setSize(originalSize);
    }

    /**
     * Removes the main component of <code>this</code> popup gallery.
     *
     * @return The removed main component.
     */
    public Component removeComponent() {
      this.remove(this.component);
      return this.component;
    }

    /**
     * Returns the main component of <code>this</code> popup gallery.
     *
     * @return The main component.
     */
    public Component getComponent() {
      return this.component;
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
   */
  public static ComponentUI createUI(JComponent c) {
    return new BasicRibbonBandUI();
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.plaf.ComponentUI#installUI(javax.swing.JComponent)
   */
  @Override
  public void installUI(JComponent c) {
    this.ribbonBand = (AbstractRibbonBand) c;

    this.rolloverTimeline = new Timeline(this);
    this.rolloverTimeline.addPropertyToInterpolate("rolloverAmount", 0.0f,
        1.0f);
    this.rolloverTimeline.addCallback(new SwingRepaintCallback(
        this.ribbonBand));
    this.rolloverTimeline.setDuration(250);

    installDefaults();
    installComponents();
    installListeners();
    c.setLayout(createLayoutManager());
    AWTRibbonEventListener.install();
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.plaf.ComponentUI#uninstallUI(javax.swing.JComponent)
   */
  @Override
  public void uninstallUI(JComponent c) {
    c.setLayout(null);
    uninstallListeners();
    uninstallDefaults();
    uninstallComponents();
    if (!AWTRibbonEventListener.uninstall()) {
      // should remove other methods of tracking
    }
  }

  /**
   * Installs default parameters on the associated ribbon band.
   */
  protected void installDefaults() {
    Color bg = this.ribbonBand.getBackground();
    if (bg == null || bg instanceof UIResource) {
      this.ribbonBand.setBackground(FlamingoUtilities.getColor(
          Color.lightGray, "RibbonBand.background",
          "Panel.background"));
    }

    Border b = this.ribbonBand.getBorder();
    if (b == null || b instanceof UIResource) {
      Border toSet = UIManager.getBorder("RibbonBand.border");
      if (toSet == null)
        toSet = new BorderUIResource(new RoundBorder(FlamingoUtilities
            .getBorderColor(), new Insets(2, 2, 2, 2)));
      this.ribbonBand.setBorder(toSet);
    }
  }

  /**
   * Installs subcomponents on the associated ribbon band.
   */
  protected void installComponents() {
    this.collapsedButton = new JCommandButton(this.ribbonBand.getTitle(),
        this.ribbonBand.getIcon());
    this.collapsedButton.setDisplayState(CommandButtonDisplayState.BIG);
    this.collapsedButton
        .setCommandButtonKind(JCommandButton.CommandButtonKind.POPUP_ONLY);
    this.collapsedButton.setPopupKeyTip(this.ribbonBand
        .getCollapsedStateKeyTip());
    this.ribbonBand.add(this.collapsedButton);

    if (this.ribbonBand.getExpandActionListener() != null) {
      this.expandButton = this.createExpandButton();
      this.ribbonBand.add(this.expandButton);
    }
  }

  /**
   * Creates the expand button for the associated ribbon band.
   *
   * @return Expand button for the associated ribbon band.
   */
  protected JCommandButton createExpandButton() {
    ResizableIcon icon = FlamingoUtilities
        .getRibbonBandExpandIcon(this.ribbonBand);
    JCommandButton result = new JCommandButton(null, icon);
    result.setFlat(true);
    result.putClientProperty(BasicCommandButtonUI.EMULATE_SQUARE_BUTTON,
        Boolean.TRUE);
    result.setBorder(new EmptyBorder(3, 2, 3, 2));
    result.setActionKeyTip(this.ribbonBand.getExpandButtonKeyTip());
    result.setActionRichTooltip(this.ribbonBand
        .getExpandButtonRichTooltip());
    return result;
  }

  protected void syncExpandButtonIcon() {
    this.expandButton.setIcon(FlamingoUtilities
        .getRibbonBandExpandIcon(this.ribbonBand));
  }

  /**
   * Installs listeners on the associated ribbon band.
   */
  protected void installListeners() {
    // without this empty adapter, the global listener never
    // gets mouse entered events on the ribbon band
    this.mouseListener = new MouseAdapter() {
    };
    this.ribbonBand.addMouseListener(this.mouseListener);

    configureExpandButton();

    this.propertyChangeListener = new PropertyChangeListener() {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
        if ("title".equals(evt.getPropertyName()))
          ribbonBand.repaint();
        if ("expandButtonKeyTip".equals(evt.getPropertyName())) {
          if (expandButton != null) {
            expandButton
                .setActionKeyTip((String) evt.getNewValue());
          }
        }
        if ("expandButtonRichTooltip".equals(evt.getPropertyName())) {
          if (expandButton != null) {
            expandButton.setActionRichTooltip((RichTooltip) evt
                .getNewValue());
          }
        }
        if ("collapsedStateKeyTip".equals(evt.getPropertyName())) {
          if (collapsedButton != null) {
            collapsedButton.setPopupKeyTip((String) evt
                .getNewValue());
          }
        }
        if ("expandActionListener".equals(evt.getPropertyName())) {
          ActionListener oldListener = (ActionListener) evt
              .getOldValue();
          ActionListener newListener = (ActionListener) evt
              .getNewValue();

          if ((oldListener != null) && (newListener == null)) {
            // need to remove
            unconfigureExpandButton();
            ribbonBand.remove(expandButton);
            expandButton = null;
            ribbonBand.revalidate();
          }
          if ((oldListener == null) && (newListener != null)) {
            // need to add
            expandButton = createExpandButton();
            configureExpandButton();
            ribbonBand.add(expandButton);
            ribbonBand.revalidate();
          }
          if ((oldListener != null) && (newListener != null)) {
            // need to reconfigure
            expandButton.removeActionListener(oldListener);
            expandButton.addActionListener(newListener);
          }
        }
        if ("componentOrientation".equals(evt.getPropertyName())) {
          if (expandButton != null) {
            syncExpandButtonIcon();
          }
        }
      }
    };
    this.ribbonBand.addPropertyChangeListener(this.propertyChangeListener);
  }

  protected void configureExpandButton() {
    if (this.expandButton != null) {
      this.expandButton.addActionListener(this.ribbonBand
          .getExpandActionListener());

      this.expandButtonActionListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          SwingUtilities.invokeLater(new Runnable() {
            public void run() {
              trackMouseCrossing(false);
            }
          });
        }
      };
      this.expandButton
          .addActionListener(this.expandButtonActionListener);
    }
  }

  /**
   * Uninstalls default parameters from the associated ribbon band.
   */
  protected void uninstallDefaults() {
    LookAndFeel.uninstallBorder(this.ribbonBand);
  }

  /**
   * Uninstalls components from the associated ribbon band.
   */
  protected void uninstallComponents() {
    if (this.collapsedButton.isVisible()) {
      // restore the control panel to the ribbon band.
      CollapsedButtonPopupPanel popupPanel = (collapsedButton
          .getPopupCallback() == null) ? null
          : (CollapsedButtonPopupPanel) collapsedButton
              .getPopupCallback().getPopupPanel(collapsedButton);
      if (popupPanel != null) {
        AbstractRibbonBand bandFromPopup = (AbstractRibbonBand) popupPanel
            .removeComponent();
        ribbonBand.setControlPanel(bandFromPopup.getControlPanel());
        ribbonBand.setPopupRibbonBand(null);
        collapsedButton.setPopupCallback(null);
      }
    }

    this.ribbonBand.remove(this.collapsedButton);
    this.collapsedButton = null;

    if (this.expandButton != null)
      this.ribbonBand.remove(this.expandButton);

    this.expandButton = null;
    this.ribbonBand = null;
  }

  /**
   * Uninstalls listeners from the associated ribbon band.
   */
  protected void uninstallListeners() {
    this.ribbonBand
        .removePropertyChangeListener(this.propertyChangeListener);
    this.propertyChangeListener = null;

    this.ribbonBand.removeMouseListener(this.mouseListener);
    this.mouseListener = null;

    unconfigureExpandButton();
  }

  protected void unconfigureExpandButton() {
    if (this.expandButton != null) {
      this.expandButton
          .removeActionListener(this.expandButtonActionListener);
      this.expandButtonActionListener = null;
      this.expandButton.removeActionListener(this.ribbonBand
          .getExpandActionListener());
    }
  }

  /**
   * Invoked by <code>installUI</code> to create a layout manager object to
   * manage the {@link JCommandButtonStrip}.
   *
   * @return a layout manager object
   */
  protected LayoutManager createLayoutManager() {
    return new RibbonBandLayout();
  }

  /**
   * Layout for the ribbon band.
   *
   * @author Kirill Grouchnikov
   */
  private class RibbonBandLayout implements LayoutManager {

    /*
     * (non-Javadoc)
     *
     * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String,
     * java.awt.Component)
     */
    public void addLayoutComponent(String name, Component c) {
    }

    /*
     * (non-Javadoc)
     *
     * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
     */
    public void removeLayoutComponent(Component c) {
    }

    /*
     * (non-Javadoc)
     *
     * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
     */
    public Dimension preferredLayoutSize(Container c) {
      Insets ins = c.getInsets();
      AbstractBandControlPanel controlPanel = ribbonBand
          .getControlPanel();
      boolean useCollapsedButton = (controlPanel == null)
          || (!controlPanel.isVisible());
      int width = useCollapsedButton ? collapsedButton.getPreferredSize().width
          : controlPanel.getPreferredSize().width;
      int height = (useCollapsedButton ? collapsedButton
          .getPreferredSize().height : controlPanel
          .getPreferredSize().height)
          + getBandTitleHeight();

      // System.out.println(ribbonBand.getTitle() + ":" + height);

      // Preferred height of the ribbon band is:
      // 1. Insets on top and bottom
      // 2. Preferred height of the control panel
      // 3. Preferred height of the band title panel
      // System.out.println("Ribbon band pref = "
      // + (height + ins.top + ins.bottom));

      return new Dimension(width + 2 + ins.left + ins.right, height
          + ins.top + ins.bottom);
    }

    /*
     * (non-Javadoc)
     *
     * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
     */
    public Dimension minimumLayoutSize(Container c) {
      Insets ins = c.getInsets();
      AbstractBandControlPanel controlPanel = ribbonBand
          .getControlPanel();
      boolean useCollapsedButton = (controlPanel == null)
          || (!controlPanel.isVisible());
      int width = useCollapsedButton ? collapsedButton.getMinimumSize().width
          : controlPanel.getMinimumSize().width;
      int height = useCollapsedButton ? collapsedButton.getMinimumSize().height
          + getBandTitleHeight()
          : controlPanel.getMinimumSize().height
              + getBandTitleHeight();

      // System.out.println(useCollapsedButton + ":" + height);

      // Preferred height of the ribbon band is:
      // 1. Insets on top and bottom
      // 2. Preferred height of the control panel
      // 3. Preferred height of the band title panel
      return new Dimension(width + 2 + ins.left + ins.right, height
          + ins.top + ins.bottom);

    }

    /*
     * (non-Javadoc)
     *
     * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
     */
    public void layoutContainer(Container c) {
      // System.out.println("Ribbon band real = " + c.getHeight());
      if (!c.isVisible())
        return;
      Insets ins = c.getInsets();

      int availableHeight = c.getHeight() - ins.top - ins.bottom;
      RibbonBandResizePolicy resizePolicy = ((AbstractRibbonBand) c)
          .getCurrentResizePolicy();

      if (resizePolicy instanceof IconRibbonBandResizePolicy) {
        collapsedButton.setVisible(true);
        int w = collapsedButton.getPreferredSize().width;
        // System.out.println("Width for collapsed of '"
        // + ribbonBand.getTitle() + "' is " + w);
        collapsedButton.setBounds((c.getWidth() - w) / 2, ins.top, w, c
            .getHeight()
            - ins.top - ins.bottom);

        // System.out.println("Collapsed " + collapsedButton.getHeight()
        // + ":" + c.getHeight());

        if (collapsedButton.getPopupCallback() == null) {
          final AbstractRibbonBand popupBand = ribbonBand.cloneBand();
          popupBand.setControlPanel(ribbonBand.getControlPanel());
          List<RibbonBandResizePolicy> resizePolicies = ribbonBand
              .getResizePolicies();
          popupBand.setResizePolicies(resizePolicies);
          RibbonBandResizePolicy largest = resizePolicies.get(0);
          popupBand.setCurrentResizePolicy(largest);
          int gap = popupBand.getControlPanel().getUI()
              .getLayoutGap();
          final Dimension size = new Dimension(ins.left + ins.right
              + gap
              + largest.getPreferredWidth(availableHeight, gap),
              ins.top
                  + ins.bottom
                  + Math.max(c.getHeight(), ribbonBand
                      .getControlPanel()
                      .getPreferredSize().height
                      + getBandTitleHeight()));
          // System.out.println(ribbonBand.getTitle() + ":"
          // + size.getHeight());
          collapsedButton.setPopupCallback(new PopupPanelCallback() {
            @Override
            public JPopupPanel getPopupPanel(
                JCommandButton commandButton) {
              return new CollapsedButtonPopupPanel(popupBand,
                  size);
            }
          });
          // collapsedButton.setGallery(new JPopupGallery(ribbonBand
          // .getControlPanel(), size));
          ribbonBand.setControlPanel(null);
          ribbonBand.setPopupRibbonBand(popupBand);
        }

        if (expandButton != null)
          expandButton.setBounds(0, 0, 0, 0);

        return;
      }

      if (collapsedButton.isVisible()) {
        // was icon and now is normal band - have to restore the
        // control panel
        CollapsedButtonPopupPanel popupPanel = (collapsedButton
            .getPopupCallback() != null) ? (CollapsedButtonPopupPanel) collapsedButton
            .getPopupCallback().getPopupPanel(collapsedButton)
            : null;
        if (popupPanel != null) {
          AbstractRibbonBand bandFromPopup = (AbstractRibbonBand) popupPanel
              .removeComponent();
          ribbonBand.setControlPanel(bandFromPopup.getControlPanel());
          ribbonBand.setPopupRibbonBand(null);
          collapsedButton.setPopupCallback(null);
        }
      }
      collapsedButton.setVisible(false);

      AbstractBandControlPanel controlPanel = ribbonBand
          .getControlPanel();
      controlPanel.setVisible(true);
      controlPanel.setBounds(ins.left, ins.top, c.getWidth() - ins.left
          - ins.right, c.getHeight() - getBandTitleHeight() - ins.top
          - ins.bottom);
      controlPanel.doLayout();

      if (expandButton != null) {
        int ebpw = expandButton.getPreferredSize().width;
        int ebph = expandButton.getPreferredSize().height;
        int maxHeight = getBandTitleHeight() - 4;
        if (ebph > maxHeight)
          ebph = maxHeight;

        int expandButtonBottomY = c.getHeight()
            - (getBandTitleHeight() - ebph) / 2;

        boolean ltr = ribbonBand.getComponentOrientation()
            .isLeftToRight();

        if (ltr) {
          expandButton.setBounds(c.getWidth() - ins.right - ebpw,
              expandButtonBottomY - ebph, ebpw, ebph);
        } else {
          expandButton.setBounds(ins.left,
              expandButtonBottomY - ebph, ebpw, ebph);
        }
      }
    }
  }

  /**
   * Event listener to handle global ribbon events. Currently handles:
   * <ul>
   * <li>Marking a ribbon band to be hovered when the mouse moves over it.</li>
   * <li>Mouse wheel events anywhere in the ribbon to rotate the selected
   * task.</li>
   * </ul>
   */
  private static class AWTRibbonEventListener implements AWTEventListener {
    private static AWTRibbonEventListener instance;
    private int installCount = 0;
    private AbstractRibbonBand lastHovered;

    public static void install() {
      if (instance == null) {
        instance = new AWTRibbonEventListener();
        java.security.AccessController
            .doPrivileged(new java.security.PrivilegedAction<Object>() {
              public Object run() {
                Toolkit
                    .getDefaultToolkit()
                    .addAWTEventListener(
                        instance,
                        AWTEvent.MOUSE_EVENT_MASK
                            | AWTEvent.MOUSE_WHEEL_EVENT_MASK);
                return null;
              }
            });
      }
      instance.installCount++;
    }

    public static boolean uninstall() {
      if (instance != null) {
        instance.installCount--;
        if (instance.installCount == 0) {
          // really uninstall
          Toolkit.getDefaultToolkit()
              .removeAWTEventListener(instance);
          instance = null;
        }
        return true;
      }
      return false;
    }

    public void eventDispatched(AWTEvent event) {
      MouseEvent mouseEvent = (MouseEvent) event;
      if (mouseEvent.getID() == MouseEvent.MOUSE_ENTERED) {
        Object object = event.getSource();
        if (!(object instanceof Component)) {
          return;
        }
        Component component = (Component) object;
        AbstractRibbonBand band = (component instanceof AbstractRibbonBand) ? ((AbstractRibbonBand) component)
            : (AbstractRibbonBand) SwingUtilities
                .getAncestorOfClass(AbstractRibbonBand.class,
                    component);
        setHoveredBand(band);
      }

      if (mouseEvent.getID() == MouseEvent.MOUSE_WHEEL) {
        if (PopupPanelManager.defaultManager().getShownPath().size() > 0)
          return;

        Object object = event.getSource();
        if (!(object instanceof Component)) {
          return;
        }
        Component component = (Component) object;
        // get the deepest subcomponent at the event point
        MouseWheelEvent mouseWheelEvent = (MouseWheelEvent) mouseEvent;
        Component deepest = SwingUtilities.getDeepestComponentAt(
            component, mouseWheelEvent.getX(), mouseWheelEvent
                .getY());
        JRibbon ribbon = (JRibbon) SwingUtilities.getAncestorOfClass(
            JRibbon.class, deepest);
        if (ribbon != null) {
          // if the mouse wheel scroll has happened inside a ribbon,
          // ask the UI delegate to handle it
          ribbon.getUI().handleMouseWheelEvent(
              (MouseWheelEvent) mouseEvent);
        }
      }
    }

    private void setHoveredBand(AbstractRibbonBand band) {
      if (lastHovered == band) {
        return; // nothing to do as we are already over
      }
      if (lastHovered != null) {
        // RibbonBandUI ui = lastHovered.getUI();
        lastHovered.getUI().trackMouseCrossing(false);
      }
      lastHovered = band;
      if (band != null) {
        band.getUI().trackMouseCrossing(true);
      }
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.plaf.ComponentUI#update(java.awt.Graphics,
   * javax.swing.JComponent)
   */
  @Override
  public void update(Graphics g, JComponent c) {
    Graphics2D g2d = (Graphics2D) g.create();
    RenderingUtils.installDesktopHints(g2d);
    super.update(g2d, c);
    g2d.dispose();
  }

  /*
   * (non-Javadoc)
   *
   * @see javax.swing.plaf.ComponentUI#paint(java.awt.Graphics,
   * javax.swing.JComponent)
   */
  @Override
  public void paint(Graphics g, JComponent c) {
    Graphics2D graphics = (Graphics2D) g.create();

    Insets ins = ribbonBand.getInsets();

    this.paintBandBackground(graphics, new Rectangle(0, 0, c.getWidth(), c
        .getHeight()));

    if (!(ribbonBand.getCurrentResizePolicy() instanceof IconRibbonBandResizePolicy)) {
      String title = ribbonBand.getTitle();
      int titleHeight = getBandTitleHeight();

      int bandTitleTopY = c.getHeight() - titleHeight;

      this.paintBandTitleBackground(graphics, new Rectangle(0,
          bandTitleTopY, c.getWidth(), titleHeight), title);
      boolean ltr = ribbonBand.getComponentOrientation().isLeftToRight();
      int titleWidth = c.getWidth() - 2 * ins.left - 2 * ins.right;
      int titleX = 2 * ins.left;
      if (expandButton != null) {
        if (ltr) {
          titleWidth = expandButton.getX() - 2 * ins.right - 2
              * ins.left;
        } else {
          titleWidth = ribbonBand.getWidth() - expandButton.getX()
              - expandButton.getWidth() - 2 * ins.right - 2
              * ins.left;
          titleX = expandButton.getX() + expandButton.getWidth() + 2
              * ins.left;
        }
      }
      this.paintBandTitle(graphics, new Rectangle(titleX, bandTitleTopY,
          titleWidth, titleHeight), title);
    }

    graphics.dispose();
  }

  /**
   * Paints band title pane.
   *
   * @param g
   *            Graphics context.
   * @param titleRectangle
   *            Rectangle for the title pane.
   * @param title
   *            Title string.
   */
  protected void paintBandTitle(Graphics g, Rectangle titleRectangle,
      String title) {
    // fix for issue 10 - empty ribbon band
    if (titleRectangle.width <= 0)
      return;

    Graphics2D graphics = (Graphics2D) g.create();
    graphics.setFont(FlamingoUtilities.getFont(this.ribbonBand,
        "Ribbon.font", "Button.font", "Panel.font"));

    FontMetrics fm = graphics.getFontMetrics();
    int y = titleRectangle.y - 2 + (titleRectangle.height + fm.getAscent())
        / 2;

    int currLength = (int) fm.getStringBounds(title, g).getWidth();
    String titleToPaint = title;
    while (currLength > titleRectangle.width) {
      title = title.substring(0, title.length() - 1);
      titleToPaint = title + "...";
      currLength = (int) fm.getStringBounds(titleToPaint, g).getWidth();
    }

    int x = titleRectangle.x + (titleRectangle.width - currLength) / 2;
    graphics.setColor(this.ribbonBand.getForeground());
    graphics.drawString(titleToPaint, x, y);
    graphics.dispose();
  }

  /**
   * Paints band title pane.
   *
   * @param g
   *            Graphics context.
   * @param titleRectangle
   *            Rectangle for the title pane.
   * @param title
   *            Title string.
   */
  protected void paintBandTitleBackground(Graphics g,
      Rectangle titleRectangle, String title) {

    Graphics2D g2d = (Graphics2D) g.create();
    g2d.setComposite(AlphaComposite.SrcOver
        .derive(0.7f + 0.3f * this.rolloverAmount));

    FlamingoUtilities.renderSurface(g2d, this.ribbonBand, titleRectangle,
        this.rolloverAmount > 0.0f, true, false);

    g2d.dispose();
  }

  public void setRolloverAmount(float rolloverAmount) {
    this.rolloverAmount = rolloverAmount;
  }

  /**
   * Paints band background.
   *
   * @param graphics
   *            Graphics context.
   * @param toFill
   *            Rectangle for the background.
   */
  protected void paintBandBackground(Graphics graphics, Rectangle toFill) {
    graphics.setColor(ribbonBand.getBackground());
    graphics.fillRect(toFill.x, toFill.y, toFill.width, toFill.height);
  }

  @Override
  public float getRolloverAmount() {
    return this.rolloverAmount;
  }

  /**
   * Returns the height of the ribbon band title area.
   *
   * @return The height of the ribbon band title area.
   */
  @Override
  public int getBandTitleHeight() {
    Font font = FlamingoUtilities.getFont(this.ribbonBand, "Ribbon.font",
        "Button.font", "Panel.font");
    if (font == null) {
      // Nimbus - is that you?
      font = new JLabel().getFont();
    }
    int result = font.getSize() + 5;
    if (result % 2 == 0)
      result++;
    return result;
  }

  /**
   * Round border for the ribbon bands.
   *
   * @author Kirill Grouchnikov
   */
  protected static class RoundBorder implements Border {
    /**
     * Border color.
     */
    protected Color color;

    /**
     * Border insets.
     */
    protected Insets insets;

    /**
     * Creates the new border.
     *
     * @param color
     *            Border color.
     * @param insets
     *            Border insets.
     */
    public RoundBorder(Color color, Insets insets) {
      this.color = color;
      this.insets = insets;
    }

    @Override
    public Insets getBorderInsets(Component c) {
      return this.insets;
    }

    @Override
    public boolean isBorderOpaque() {
      return false;
    }

    @Override
    public void paintBorder(Component c, Graphics g, int x, int y,
        int width, int height) {
      Graphics2D g2d = (Graphics2D) g.create();
      g2d.setColor(this.color);
      g2d.drawRoundRect(x, y, width - 1, height - 1, 3, 3);
      g2d.dispose();
    }

  }

  @Override
  public int getPreferredCollapsedWidth() {
    return this.collapsedButton.getPreferredSize().width + 2;
  }

  @Override
  public void trackMouseCrossing(boolean isMouseIn) {
    if (isMouseIn) {
      this.rolloverTimeline.play();
    } else {
      this.rolloverTimeline.playReverse();
    }
    this.ribbonBand.repaint();
  }

  /**
   * This method is for unit tests only and should not be called by the
   * application code.
   *
   * @return The expand button of the matching ribbon band.
   */
  public AbstractCommandButton getExpandButton() {
    return this.expandButton;
  }
}
TOP

Related Classes of org.pushingpixels.flamingo.internal.ui.ribbon.BasicRibbonBandUI$CollapsedButtonPopupPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.